package com.link.base.base.fund.service;


import com.link.base.user.model.CoreUser;
import com.link.base.base.user.model.User;
import com.link.base.base.fund.dao.mybatis.mapper.BillAccountDetailMapper;
import com.link.base.base.fund.model.BillAccount;
import com.link.base.base.fund.model.BillAccountDetail;
import com.link.base.base.staticvalue.model.Staticvalue;
import com.link.base.base.staticvalue.service.StaticvalueServiceImpl;
import com.link.base.base.user.service.UserService;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.ServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.util.UserUtil;
import com.link.base.core.basic.util.YmlConstants;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

/**
 * Copyright  hande Company. All Rights Reserved.
 *
 * @author  crm4
 * @date:   2018-06-26
 * @version 1.0
 */


@Service
public class BillAccountDetailServiceImpl extends BasicServiceImpl<BillAccountDetail> implements BillAccountDetailService {

    /**
     * 财务对账单现金账户对应的类型
     */
    private static final  String  CASH_ACCNT_TYPE  = "Cash Account";
    /**
     * 财务对账单返利账户对应的类型
     */
    private static final  String  RETURN_ACCNT_TYPE  = "Return Account";
    /**
     * 财务对账单保证金账户对应的类型
     */
    private static final  String  DEPOSIT_ACCNT_TYPE  = "Deposit Account";
    /**
     * 财务对账单对应的交易类型
     */
    private static final  String  TRANSACTION_SOURCE_TYPE  = "TRANSACTION_SOURCE_TYPE";
    /**
     * pdf字体文件在portalshare 目录下的路径
     */
    private static final  String  FONT_FILE_PATH = "/pdffont/msyhl.ttc,0";
    /**
     * 数字格式化
     */
    public static final  DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
    @Resource
    private BillAccountDetailMapper billAccountDetailMapper;
    @Resource
    private StaticvalueServiceImpl staticvalueService;
    @Resource
    private BillAccountService  billAccountService;
    @Resource
    private UserService userService;

    @Override
    public BasicMapper<BillAccountDetail> getBasicMapper() {
        return billAccountDetailMapper;
    }


    /**
     * 指定对账单头 删除对账单明细
     *
     * @param billAccountDetail
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void deleteByHeadId(BillAccountDetail billAccountDetail) throws Exception {
        billAccountDetailMapper.deleteByHeadId(billAccountDetail);
    }

    @Override
    public String printBillPdf(BillAccountDetail billAccountDetail) throws Exception {

        BillAccount account = new BillAccount();
        Long accntId = billAccountDetail.getHeadId();
        account.setId(accntId);
        BillAccount billAccount = billAccountService.queryById(account);
        if (billAccount == null) {
            throw new ServiceException("FUND-001");
        }

        String[] heads = {"序号", "业务单号", "交易时间", "交易类型", "交易金额"};
        List<BillAccountDetail> billAccountDetails = this.queryByExamplePage(billAccountDetail);

        //设置字体
        String  fontPath = YmlConstants.getPortalShareFileDir() + FONT_FILE_PATH;
        BaseFont bfChinese = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        Font titleFont = new Font(bfChinese, 22);

        //创建文件
        Document document = new Document();
        PdfWriter writer = null;
        String filePath = YmlConstants.getTemporaryIOFileDir();
        String subPath = "/billaccnt/crm/";
        String fileStorePath = getStoreFilePath(billAccountDetail, filePath, subPath);
        try {
            writer = PdfWriter.getInstance(document, new FileOutputStream(filePath + fileStorePath));
            //打开文件
            document.open();

            Paragraph paragraph = new Paragraph("财务对账单", titleFont);
            paragraph.setAlignment(Element.ALIGN_CENTER);
            //添加内容
            document.add(paragraph);

            //设置账单信息
            setCustomerMsg(document, billAccount, bfChinese);
            //分别设置现金、返利、保证金等账户表的内容
            setContent(billAccount, heads, billAccountDetails, bfChinese, document);


            return YmlConstants.getTemporaryIOUrlDir() + fileStorePath;
        } finally {
            //关闭文档
            document.close();
            //关闭书写器
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * 获取文件存储路径
     * @author guoshan
     * @date 2019/03/19
     * @param billAccountDetail 对账单详情
     * @param filePath  文件存储的上级目录，从配置文件中获取
     * @param subPath   文件存储的子目录，自定义，由于区分不同模块的文件
     * @return  文件存储的子路径，有自定义目录和文件名组成
     */
    private String getStoreFilePath(BillAccountDetail billAccountDetail, String filePath, String subPath) {
        File file = new File(filePath + subPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        SimpleDateFormat datetimeFormatter = new SimpleDateFormat("yyyyMMddHHmmsss");
        String  fileName = datetimeFormatter.format(new Date()) + "_" + billAccountDetail.getHeadId();
        //建立一个书写器
        return subPath + fileName + ".pdf";
    }

    /**
     * 向PDF文档中添加数据:现金、返利、保证金账户
     * @author guoshan
     * @date 2019/03/19
     * @param billAccount   对账单
     * @param heads 文档中表格中每列的名称
     * @param billAccountDetails    对账单明细
     * @param bfChinese 文档表格中数据显示的字体
     * @param document  要添加数据的文档
     */
    private void setContent(BillAccount billAccount, String[] heads,
                            List<BillAccountDetail> billAccountDetails,
                            BaseFont bfChinese, Document document) throws Exception {
        Font fontChinese12 = new Font(bfChinese, 12, Font.NORMAL);
        //设置列宽
        float[] columnWidths = { 1f, 3f, 3f, 2f, 2f };
        //现金账户表
        PdfPTable table = getTable(heads.length,columnWidths);
        List<PdfPRow> listRow = table.getRows();
        //返利账户表
        PdfPTable table1 = getTable(heads.length,columnWidths);
        List<PdfPRow> listRow1 = table1.getRows();

        //保证金账户表
        PdfPTable table2 = getTable(heads.length,columnWidths);
        List<PdfPRow> listRow2 = table2.getRows();

        PdfPCell[] headCells = new PdfPCell[heads.length];
        for (int i = 0; i < heads.length; i++) {
            headCells[i] = new PdfPCell(new Paragraph(heads[i],fontChinese12));
            headCells[i].setMinimumHeight(24);
        }
        PdfPRow headRow = new PdfPRow(headCells);
        listRow.add(headRow);
        listRow1.add(headRow);
        listRow2.add(headRow);
        int cashCount = 1;
        int returnCount = 1;
        int depositCount = 1;

        Map<String,String>  map = getValueName(TRANSACTION_SOURCE_TYPE);
        for (BillAccountDetail  accountDetail : billAccountDetails) {
            PdfPCell[] cells = new PdfPCell[heads.length];
            PdfPRow row = new PdfPRow(cells);
            String  accntType = accountDetail.getAccntType();
            cells[1] = new PdfPCell(new Paragraph(accountDetail.getSourceNum()));
            cells[1].setMinimumHeight(24);
            cells[2] = new PdfPCell(new Paragraph(accountDetail.getDealTime()));
            cells[2].setMinimumHeight(24);
            cells[3] = new PdfPCell(new Paragraph(map.get(accountDetail.getSourceType()),fontChinese12));
            cells[3].setMinimumHeight(24);
            cells[4] = new PdfPCell(new Paragraph(formatData(accountDetail.getAmount())));
            cells[4].setMinimumHeight(24);
            if ( CASH_ACCNT_TYPE.equals(accntType)) {
                cells[0] = new PdfPCell(new Paragraph(cashCount + ""));
                listRow.add(row);
                cashCount ++ ;
            } else if (RETURN_ACCNT_TYPE.equals(accntType)) {
                cells[0] = new PdfPCell(new Paragraph(returnCount + ""));
                listRow1.add(row);
                returnCount ++ ;
            } else {
                cells[0] = new PdfPCell(new Paragraph(depositCount + ""));
                listRow2.add(row);
                depositCount ++ ;
            }
            cells[0].setMinimumHeight(24);
        }
        BillAccount billAccount1 = billAccountService.sumDealerBalance(billAccount);
        setTableTitle(document,bfChinese,formatData(billAccount1.getDepositRemainAmount()),
                formatData(billAccount1.getDepositTotalAmount()) ,"现金账户");
        document.add(table);
        setTableTitle(document,bfChinese,formatData(billAccount1.getReturnRemainAmount()),
                formatData(billAccount1.getReturnTotalAmount()) ,"返利账户");
        document.add(table1);
        setTableTitle(document,bfChinese,formatData(billAccount1.getCashRemainAmount()),
                formatData(billAccount1.getCashTotalAmount()) ,"保证金账户");
        document.add(table2);

    }

    /**
     * 获取一张表格
     * @author guoshan
     * @date 2019/03/19
     * @param colNum    表格的列数
     * @param columnWidths    每列的宽度
     * @return  表格对象
     */
    private PdfPTable getTable(int colNum,float[] columnWidths) throws DocumentException {
        PdfPTable  table = new PdfPTable(colNum);
        // 宽度100%填充
        table.setWidthPercentage(100);
        table.getDefaultCell().setMinimumHeight(24);
        table.setWidths(columnWidths);
        return  table ;
    }

    /**
     * 设置文档中表格的上面的信息
     * @author guoshan
     * @date 2019/03/19
     * @param document  PDF文档对象
     * @param baseFont  显示字体
     * @param firstCash 期初金额
     * @param endCash   期末金额
     * @param type  类型
     * @throws DocumentException
     */
    public  void  setTableTitle(Document document, BaseFont baseFont,String firstCash,String endCash,String type) throws DocumentException {
        Font  font14 = new Font(baseFont,14,Font.BOLD);
        Font  font12 = new Font(baseFont,12,Font.NORMAL);
        PdfPTable table = new PdfPTable(5);
        // 宽度100%填充
        table.setWidthPercentage(100);
        // 前间距
        table.setSpacingBefore(15f);
        // 后间距
        table.setSpacingAfter(5f);
        float[] width9 = {3f,2f,2f,2f,2f};
        table.setWidths(width9);
        PdfPCell[] cells = new PdfPCell[5];
        cells[0] = new PdfPCell(new Paragraph(type,font14));
        cells[1] = new PdfPCell(new Paragraph("期初金额:",font12));
        cells[2] = new PdfPCell(new Paragraph(firstCash));
        cells[3] = new PdfPCell(new Paragraph("期末金额:",font12));
        cells[4] = new PdfPCell(new Paragraph(endCash));
        cells[0].setHorizontalAlignment(Element.ALIGN_LEFT);
        cells[1].setHorizontalAlignment(Element.ALIGN_RIGHT);
        cells[2].setHorizontalAlignment(Element.ALIGN_LEFT);
        cells[3].setHorizontalAlignment(Element.ALIGN_RIGHT);
        cells[4].setHorizontalAlignment(Element.ALIGN_LEFT);
        cells[0].setBorder(0);
        cells[0].setMinimumHeight(24);
        cells[1].setBorder(0);
        cells[1].setMinimumHeight(24);
        cells[2].setBorder(0);
        cells[2].setMinimumHeight(24);
        cells[3].setBorder(0);
        cells[3].setMinimumHeight(24);
        cells[4].setBorder(0);
        cells[4].setMinimumHeight(24);
        ArrayList<PdfPRow> rows = table.getRows();
        PdfPRow pdfPRow = new PdfPRow(cells);
        rows.add(pdfPRow);
        document.add(table);
    }


    /**
     * 设置对账单的基本信息
     * @author guoshan
     * @date 2019/03/19
     * @param document  文档对象
     * @param billAccount   对账单
     * @param bfChinese 显示字体
     */
    public  void setCustomerMsg(Document document, BillAccount billAccount,BaseFont bfChinese) throws Exception {
        Font fontChinese12 = new Font(bfChinese, 12, Font.NORMAL);
        //存储用户信息
        PdfPTable table = new PdfPTable(4);
        // 宽度100%填充
        table.setWidthPercentage(100);
        // 前间距
        table.setSpacingBefore(10f);
        // 后间距
        table.setSpacingAfter(10f); 

        List<PdfPRow> listRow = table.getRows();
        //设置列宽
        float[] columnWidths = { 1f, 2f, 1f, 3f };
        table.setWidths(columnWidths);
        PdfPCell[] cells0 = new PdfPCell[4];
        PdfPRow row0 = new PdfPRow(cells0);
        //单元格
        cells0[0] = new PdfPCell(new Paragraph("账单编号",fontChinese12));
        cells0[0].setMinimumHeight(24);
        cells0[1] = new PdfPCell(new Paragraph(billAccount.getId()));
        cells0[1].setMinimumHeight(24);
        cells0[2] = new PdfPCell(new Paragraph("客户名称",fontChinese12));
        cells0[2].setMinimumHeight(24);
        cells0[3] = new PdfPCell(new Paragraph(billAccount.getAccntName(),fontChinese12));
        cells0[3].setMinimumHeight(24);
        listRow.add(row0);

        PdfPCell[] cells01 = new PdfPCell[4];
        PdfPRow row01 = new PdfPRow(cells01);
        cells01[0] = new PdfPCell(new Paragraph("对账期间",fontChinese12));
        cells01[0].setMinimumHeight(24);
        cells01[1] = new PdfPCell(new Paragraph(billAccount.getPeriodTitle()));
        cells01[1].setMinimumHeight(24);
        cells01[2] = new PdfPCell(new Paragraph("期间时间",fontChinese12));
        cells01[2].setMinimumHeight(24);
        cells01[3] = new PdfPCell(new Paragraph(billAccount.getStartDate() + "至" + billAccount.getEndDate(),fontChinese12));
        cells01[3].setMinimumHeight(24);
        listRow.add(row01);

        PdfPCell[] cells02 = new PdfPCell[4];
        PdfPRow row02 = new PdfPRow(cells02);
        cells02[0] = new PdfPCell(new Paragraph("制单时间",fontChinese12));
        cells02[0].setMinimumHeight(24);
        cells02[1] = new PdfPCell(new Paragraph(billAccount.getCreated()));
        cells02[1].setMinimumHeight(24);
        cells02[2] = new PdfPCell(new Paragraph("制单人",fontChinese12));
        cells02[2].setMinimumHeight(24);
        User userSource = new User();
        userSource.setId(billAccount.getCreatedBy());
        User user = userService.queryById(userSource);
        cells02[3] = new PdfPCell(new Paragraph(user.getFirstName(),fontChinese12));
        listRow.add(row02);
        document.add(table);

    }

    /**
     * 格式化double类型的数据，保留两位小数。
     * @author guoshan
     * @date 2019/03/21
     * @param data 要格式化的数据
     * @return  格式化后的数据
     */
    private String formatData(Double data) {
        if (data == null) {
            return  "0.00";
        }
        df.setMaximumFractionDigits(2);
        return df.format(data);
    }

    /**
     * 根据值列表类型获取值列表的显示值
     * @author guoshan
     * @date 2019/03/19
     * @param type 值列表类型
     */
    private Map<String, String> getValueName(String type ) throws Exception {
        CoreUser user = UserUtil.getUser();
        if (user == null) {
            throw new ServiceException("PUBLIC-023");
        }
        Staticvalue staticvalue = new Staticvalue();
        staticvalue.setLoginCorpId(user.getLoginCorpId());
        Map<String,String> typeViewVlue = new HashMap<>();
        staticvalue.setType(type);
        List<Staticvalue> staticvalues = staticvalueService.queryByLovType(staticvalue);
        for (Staticvalue  staticvalue1 : staticvalues ) {
            typeViewVlue.put(staticvalue1.getVal(),staticvalue1.getName());
        }
        return typeViewVlue;
    }

}
